﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Urb.Weather.Core;
using System.ComponentModel.Composition;
using Urb.Weather.Core.Provider;
using Urb.Weather.Core.Engine;
using Urb.Weather.Core.Configuration;

namespace Urb.Weather.Yahoo
{
    public class YahooWeatherDataProvider : IWeatherDataProvider
    {        
        public WeatherDataProviderConfigurationDefinition ConfigurationDefinition
        {
            get { return new WeatherDataProviderConfigurationDefinition(); }
        }

        public string SourceName
        {
            get { return "Yahoo"; }
        }

        public void InitializeInstance(
            IWeatherDataProviderInstanceRegistrationToken instanceRegistrationToken,
            IEngine engine, 
            IWeatherDataProviderConfiguration configuration,
            Action<IWeatherDataProviderInstanceRegistrationToken, WeatherData> dataRefreshed)
        {
            if (instanceRegistrationToken == null)
                throw new ArgumentNullException("instanceRegistrationToken");

            if (engine == null)
                throw new ArgumentNullException("engine");

            if (configuration == null)
                throw new ArgumentNullException("configuration");

            if (!(configuration is YahooWeatherDataProviderConfiguration))
                throw new ArgumentException("configuration");

            var config = configuration.Clone() as YahooWeatherDataProviderConfiguration;

            engine.Queue(
                new WorkItem<
                    IWeatherDataProviderInstanceRegistrationToken,
                    IEngine,
                    YahooWeatherDataProviderConfiguration,
                    Action<IWeatherDataProviderInstanceRegistrationToken, WeatherData>>()
                {
                    Parameter1 = instanceRegistrationToken,
                    Parameter2 = engine,
                    Parameter3 = config,
                    Parameter4 = dataRefreshed,
                    Action = Refresh
                },
                new TimeSpanPeriod(config.RefreshTimeSpan),
                new TimeSpan(0, 0, 5)
                );
        }

        private static void Refresh(
            IWeatherDataProviderInstanceRegistrationToken instanceRegistrationToken,
            IEngine engine,
            YahooWeatherDataProviderConfiguration configuration,
            Action<IWeatherDataProviderInstanceRegistrationToken, WeatherData> dataRefreshed)
        {
            var uri = new YahooWeatherUri(configuration.LocationId);

            engine.Queue(
                new DownloadStringWorkItem()
                {
                    Uri = uri.ToString(),
                    OnSuccess = r => RefreshResponseReceived(r, instanceRegistrationToken, dataRefreshed)
                    // TODO: OnError = 
                }
                );
        }

        private static void RefreshResponseReceived(
            string response,
            IWeatherDataProviderInstanceRegistrationToken instanceRegistrationToken,
            Action<IWeatherDataProviderInstanceRegistrationToken, WeatherData> dataRefreshed)
        {
            var analyzer = new YahooResponseAnalyzer();

            var concreteWeatherData = analyzer.Analyze(response);
            var weatherData = analyzer.Convert(concreteWeatherData);

            dataRefreshed(instanceRegistrationToken, weatherData);
        }
    }
}
